package com.funtl.framework.java.util.mail;

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

/**
 * 纯文本邮件
 * 
 * @author lusifer
 * 
 */
public class SMTPTextSender {
	private String send;				//发送邮件服务器信息
	private String fm;					//发件人
	private String username;			//用户名
	private String password;			//密码

	/**
	 * SMTP协议邮件，纯文本，参数可以使用MailParam中定义的常量
	 * @param send		邮件服务 - smtp.qq.com
	 * @param fm		发件人     - lwm@huahongtop.com
	 * @param username	用户名
	 * @param password	密码
	 */
	public SMTPTextSender(String send, String fm, String username, String password) {
		this.send = send;
		this.fm = fm;
		this.username = username;
		this.password = password;
	}
	
	/**
	 * 多人邮件（不会暴露出全部收件人地址）
	 * @param too 收件人
	 * @param subject 主题
	 * @param body 内容
	 * @param print 是否打印测试信息
	 * @return 0 - 发送成功，1 - 无效的地址，2 - 无效的协议，3 - 消息设置异常
	 */
	public int sendEmail(String[] too, String subject, String body, boolean print) {
		Properties props = new Properties();

		props.put(MailParam.SMTP_HOST, send);// 存储发送邮件服务器的信息
		props.put(MailParam.SMTP_AUTH, "true");// 同时通过验证
		Session s = Session.getInstance(props);// 根据属性新建一个邮件会话
		s.setDebug(print); //可以打印邮件发送相关信息

		try {
			MimeMessage message = new MimeMessage(s);// 由邮件会话新建一个消息对象
			// 设置邮件
			// 设置发件人
			InternetAddress from = new InternetAddress(fm);
			message.setFrom(from);
			
			// 设置收件人,并设置其接收类型为TO，直接数组可发送多人
			for (int i = 0 ; i < too.length ; i++)  {
				InternetAddress to = new InternetAddress(too[i]);
				message.setRecipient(Message.RecipientType.TO, to);
				message.setSubject(subject);// 设置主题
				message.setText(body);// 设置信件内容
				message.setSentDate(new Date());// 设置发信时间

				// 发送邮件
				message.saveChanges();// 存储邮件信息
				Transport transport = s.getTransport(MailParam.SMTP_PROTOCOL);
				transport.connect(send, username, password);// 以smtp方式登录邮箱
				transport.sendMessage(message, message.getAllRecipients());// 发送邮件,其中第二个参数是所有已设好的收件人地址
				transport.close();
			}
		} catch (AddressException e) {
			e.printStackTrace();
			return 1;
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			return 2;
		} catch (MessagingException e) {
			e.printStackTrace();
			return 3;
		}
		
		return 0;
	}

	/**
	 * 多人邮件（会暴露出全部收件人地址）
	 * @param too 收件人
	 * @param subject 主题
	 * @param body 内容
	 * @param print 是否打印测试信息
	 * @return 0 - 发送成功，1 - 无效的地址，2 - 无效的协议，3 - 消息设置异常
	 */
	public int sendMultiEmail(String[] too, String subject, String body, boolean print) {
		Properties props = new Properties();

		props.put(MailParam.SMTP_HOST, send);// 存储发送邮件服务器的信息
		props.put(MailParam.SMTP_AUTH, "true");// 同时通过验证
		Session s = Session.getInstance(props);// 根据属性新建一个邮件会话
		s.setDebug(print); //可以打印邮件发送相关信息

		try {
			MimeMessage message = new MimeMessage(s);// 由邮件会话新建一个消息对象
			// 设置邮件
			// 设置发件人
			InternetAddress from = new InternetAddress(fm);
			message.setFrom(from);
			// 设置收件人,并设置其接收类型为TO，直接数组可发送多人
			for (int i = 0 ; i < too.length ; i++)  {
				InternetAddress to = new InternetAddress(too[i]);
				message.addRecipient(Message.RecipientType.TO, to);
			}
			message.setSubject(subject);// 设置主题
			message.setText(body);// 设置信件内容
			message.setSentDate(new Date());// 设置发信时间

			// 发送邮件
			message.saveChanges();// 存储邮件信息
			Transport transport = s.getTransport(MailParam.SMTP_PROTOCOL);
			transport.connect(send, username, password);// 以smtp方式登录邮箱
			transport.sendMessage(message, message.getAllRecipients());// 发送邮件,其中第二个参数是所有已设好的收件人地址
			transport.close();
		} catch (AddressException e) {
			e.printStackTrace();
			return 1;
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			return 2;
		} catch (MessagingException e) {
			e.printStackTrace();
			return 3;
		}
		
		return 0;
	}
	
	/**
	 * 群发邮件（不会暴露全部收件人地址），通常会被当做垃圾邮件或因为管制等原因发送失败，即使发送成功也有可能内容加载失败
	 * @param sendSMTPAddress SMTP地址，随便填写，一般填写自家邮件域名即可，mail.w951.com
	 * @param from 发件人
	 * @param subject 主题
	 * @param body 内容
	 * @param to 收件人，数组
	 * @param print 是否打印测试信息
	 * @return 0 - 发送成功，1 - 无效的地址，2 - 消息设置异常，3 - DNS解析错误
	 */
	public int sendMassEmail(String sendSMTPAddress, String from, String subject, String body, String[] to, boolean print) {
		Properties props = new Properties();
		props.setProperty(MailParam.SMTP_LOCALHOST, sendSMTPAddress);
		Session session = Session.getInstance(props);
		session.setDebug(print);
		try {
			Message msg = createMessage(session, from, subject, body);
			for (int i = 0; i < to.length; i++) {
				sendMessage(session, msg, to[i]);
			}
		} catch (AddressException e) {
			e.printStackTrace();
			return 1;
		} catch (MessagingException e) {
			e.printStackTrace();
			return 2;
		} catch (NamingException e) {
			e.printStackTrace();
			return 3;
		}
		
		return 0;
	}
	
	private Message createMessage(Session session, String from, String subject, String body) throws AddressException, MessagingException {
		MimeMessage msg = new MimeMessage(session);
		msg.setFrom(new InternetAddress(from));
		msg.setSentDate(new Date());
		msg.setSubject(subject);
		msg.setText(body);
		return msg;
	}
	
	private void sendMessage(Session session, Message msg, String to) throws AddressException, NoSuchProviderException, MessagingException, NamingException {
		// 设置邮件内容的收件人并生成邮件消息内容
		msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
		msg.saveChanges();

		// 连接收件人地址所在的SMTP服务器并发送邮件
		Transport transport = session.getTransport(MailParam.SMTP_PROTOCOL);
		String domain = to.substring(to.indexOf("@") + 1);
		String smtpServer = getSmtpServer(domain, null);
		transport.connect(smtpServer, null, null);
		transport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));
		transport.close();
	}
	
	private String getSmtpServer(String domain, String dnsServer) throws NamingException {
		DirContext ctx = new InitialDirContext();
		Attributes attrsMx = null;
		if (dnsServer != null) {
			attrsMx = ctx.getAttributes("dns:" + "//" + dnsServer + "/" + domain, new String[] { "MX" });
		} else {
			attrsMx = ctx.getAttributes("dns:" + "/" + domain, new String[] { "MX" });
		}
		String recordMx = (String) attrsMx.get("MX").get();
		String smtpServer = recordMx.substring(recordMx.indexOf(" ") + 1);
		return smtpServer;
	}
	
	public static void main(String[] args) throws Exception {
		SMTPTextSender sender = new SMTPTextSender(MailParam.SEND_SMTP_QQ_EX, "lwm@huahongtop.com", "lwm@huahongtop.com", "lwm1303311");
		String[] to = new String[] {"topsale@vip.qq.com", "lwm@huahongtop.com", "topsale86@gmail.com"};
		
		//批量逐个发送
		sender.sendEmail(to, "这是一封批量逐个发送测试邮件", "这是一封批量逐个发送测试邮件，不会暴露全部收件人地址\r\n换行测试", true);
		
		//多人邮件（会暴露出全部收件人地址）
//		sender.sendMultiEmail(to, "这是一封多人测试邮件", "这是一封多人测试邮件，会暴露出全部收件人地址", true);
		
		//群发邮件（不会暴露全部收件人地址），mail.itcast.cn，以上域名可以发送群发邮件（目前测试，Google的可以），但会被视为垃圾邮件
//		sender.sendMassEmail("mail.itcast.cn", "lwm@huahongtop.com", "这是一封群发测试邮件", "这是一封群发测试邮件，不会暴露全部收件人地址", to, true);
	}
	
}
